import { useCallback, useEffect, useRef, useState } from "react";


export type GetResData<T extends (params: any) => Promise<any>> = T extends (
  params: any
) => Promise<infer U>
  ? U
  : never;

export const useHandle = <T extends (...params: any[]) => Promise<any>>(
  api: T,
  handleSuccess: (res: GetResData<T>) => void,
  handleFail?: (res: Error) => void
) => {
  const [loading, setLoading] = useState(false);

  const load = async (...params: Parameters<T>) => {
    setLoading(true);

    try {
      const data = await api(...params);
      setLoading(false);
      handleSuccess?.(data);

      return data;
    } catch (error) {
      setLoading(false);

      handleFail?.(error as Error);
      // throw error;
    }
  };

  return { load, loading };
};

export const useFetch = <T extends (...param: any[]) => Promise<any>, U>(
  api: T
) => {
  const [loading, setLoading] = useState(false);

  const [data, setData] = useState<GetResData<T>>();

  const loadData = async (...params: Parameters<T>) => {
    try {
      setLoading(true);
      const data = await api(...params);
      setData(data);
      setLoading(false);
    } catch (error) {
      setLoading(false);
      setData(undefined);
    }
  };

  return [
    data as U extends undefined ? undefined | GetResData<T> : GetResData<T>,
    loadData,
    loading,
  ] as const;
};

/**
 * 以前有个输入框的业务
 */
export const  useDebounce = (val:number,delay= 500) => {
  const [value,setValue] = useState(val)


    useEffect(() => {
        const timer = setTimeout(() => {
          setValue(val)
        }, delay);
        return () => clearTimeout(timer)
    },[val,delay])


    return value
} 

/** 凭理解手写节流函数，具体逻辑到了，但是需要实际的业务中测试才行。 */

export const useThrottle = (fn:Function,delay) => {
  const ref = useRef< any>()
  
  const handle = useCallback(() => {
    if (ref.current == null) {
      ref.current = setTimeout(() => {
        fn()
        clearTimeout(ref?.current)
      },delay)
    }
  },[fn,delay])

 return [ handle] as const

}


/**
 * 
 * @param getUserInfo 获取用户信息
 * @param ref 全局 ref 用于缓存变量
 * 
 */

  export function useGetInfo<T,P extends T | undefined> (getUserInfo :() =>Promise<T>,ref:React.MutableRefObject<boolean> )  {
 
  const [useInfo,setUseInfo] = useState<T>()

  const handle  = useCallback(() => {
    if (ref.current ===false) {
      getUserInfo().then(res => {
   
       setUseInfo(res)
       ref.current = true
      },() => {
        ref.current = false
        handle()
      })
     }
  },[])

 

  return [useInfo as P extends undefined ? T | undefined : T ,handle] as const

}


// 定时器封装

export const useInterval = (params: {
  then: (handleOk: () => void, handleFail: () => void) => Promise<any>;
  openDelay?: number;
  delay?: number;
  initOpen?: boolean;
}) => {
  const { then, openDelay = 1500, delay = 2000, initOpen = true } = params ?? {};
  const [once, setOnce] = useState(false);
  //
  const [result, setResult] = useState<{ success: boolean }>({ success: true });
  // 总开关
  const [open, setOpen] = useState(false);
  // 打断定时开关
  const [flag, setFlag] = useState(true);
  // 定时器
  const interval = useRef<any>();

  // 成功回调
  const handleSuccess = useCallback(() => {
    setResult({ success: true });
  }, []);
  // 失败回调
  const handleFail = useCallback(() => {
    setResult({ success: false });
  }, []);

  const handle = useCallback(() => {
    if (flag && result?.success) {
      if (!once) {
        then(handleSuccess, handleFail).then(() => {
          setOnce(true);
        });
        return;
      }
      interval.current = setTimeout(async () => {
        await then(handleSuccess, handleFail);
        clearTimeout(interval.current);
      }, delay);
    }
  }, [result, flag, once]);

  useEffect(() => {
    if (open) {
      handle();
    }
    return () => {
      clearTimeout(interval.current);
    };
  }, [handle, open]);

  useEffect(() => {
    if (initOpen) {
      let timer = setTimeout(() => {
        setOpen(true);
        clearTimeout(timer);
      }, openDelay);
    }
  }, [initOpen]);

  /**
   * 打断定时时器，
   */
  const pause = useCallback(() => {
    setFlag(false);
    setResult({ success: false });
  }, []);

  /**
   * 重新启动定时器
   */
  const regain = useCallback(() => {
    setFlag(true);
    setResult({ success: true });
  }, []);

  /**
   *  初始开关闭没有开 ,手动开启
   */
  const handMovement = useCallback(() => {
    setOpen(true);
    setFlag(true);
  }, []);

  return [flag, pause, regain, handMovement] as const;
};
